package com.bjbn.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bjbn.config.YxhtSmsConfig;
import com.bjbn.dto.SmsRequestDto;
import com.bjbn.dto.SmsResponseDto;
import com.bjbn.dto.YxhtSmsRequestDto;
import com.bjbn.dto.YxhtSmsResponseDto;
import com.bjbn.entity.YxhtApiLog;
import com.bjbn.mapper.YxhtApiLogMapper;
import com.bjbn.service.YxhtSmsService;
import com.bjbn.util.DigestAuthUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 易信华泰短信服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class YxhtSmsServiceImpl implements YxhtSmsService {

    private final YxhtSmsConfig yxhtSmsConfig;
    private final YxhtApiLogMapper yxhtApiLogMapper;

    @Override
    public SmsResponseDto sendSms(SmsRequestDto request) {
        YxhtSmsRequestDto yxhtRequest = new YxhtSmsRequestDto();
        yxhtRequest.setName(request.getName());
        yxhtRequest.setTemplateId(request.getTemplateId());
        yxhtRequest.setParams(request.getParams());
        yxhtRequest.setMobiles(request.getMobiles());
        Map<String, Object> content = new HashMap<>();
        if (request.getTemplateId() != null && !request.getTemplateId().isEmpty()) {
            content = new HashMap<>();
        } else {
            content.put("content", request.getContent());
        }
        yxhtRequest.setContent(content);

        YxhtSmsResponseDto yxhtResponse = null;
        SmsResponseDto result;
        String errorMsg = null;
        try {
            yxhtResponse = callYxhtSmsApi(yxhtRequest);
            if (yxhtResponse.getCode() == 0) {
                result = SmsResponseDto.success(yxhtResponse.getGroupid());
            } else {
                result = SmsResponseDto.error(yxhtResponse.getCode(), yxhtResponse.getMessage());
            }
        } catch (Exception e) {
            errorMsg = e.getMessage();
            log.error("发送短信失败", e);
            result = SmsResponseDto.error(-1, "发送短信失败：" + errorMsg);
        } finally {
            // 记录日志，无论成功失败
            String apiCallback = yxhtResponse != null ? JSON.toJSONString(yxhtResponse) : errorMsg;
            saveApiLog(request.getMobiles(), request.getContent(),
                    JSON.toJSONString(yxhtRequest), apiCallback);
        }
        return result;
    }

    @Override
    public SmsResponseDto sendTemplateSms(String mobiles, String templateId, String[] params, String name) {
        SmsRequestDto request = new SmsRequestDto();
        request.setMobiles(mobiles);
        request.setTemplateId(templateId);
        request.setParams(params == null ? null : Arrays.asList(params));
        request.setName(name);
        request.setContent("");
        return sendSms(request);
    }

    @Override
    public SmsResponseDto sendNormalSms(String mobiles, String content, String name) {
        SmsRequestDto request = new SmsRequestDto();
        request.setMobiles(mobiles);
        request.setContent(content);
        request.setName(name);
        request.setTemplateId("");
        return sendSms(request);
    }

    /**
     * 调用易信华泰短信平台API
     */
    private YxhtSmsResponseDto callYxhtSmsApi(YxhtSmsRequestDto request) throws Exception {
        HttpClient httpClient = HttpClients.createDefault();
        String url = yxhtSmsConfig.getBaseUrl() + yxhtSmsConfig.getSendPath();

        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "application/json");

        // 设置请求体
        String requestBody = JSON.toJSONString(request);
        httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));

        // 第一次请求（可能返回401需要认证）
        HttpResponse response = httpClient.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();
        log.info("statusCode is :" + statusCode);

        if (statusCode == 401) {
            log.info(Arrays.toString(response.getAllHeaders()));
            // 需要Digest认证
            String wwwAuth = response.getFirstHeader("WWW-Authenticate").getValue();
            log.info("wwwAuth is :");
            log.info(wwwAuth);
            String authorization = DigestAuthUtil.authorization(wwwAuth, "POST", yxhtSmsConfig.getSendPath(),
                    yxhtSmsConfig.getUsername(), yxhtSmsConfig.getPassword(), 1);
            log.info("authorization is :");
            log.info(authorization);
            // 重新发送请求，带上认证信息
            httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Authorization", authorization);
            httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));

            response = httpClient.execute(httpPost);
            statusCode = response.getStatusLine().getStatusCode();
        }

        // 解析响应
        HttpEntity entity = response.getEntity();
        String responseBody = EntityUtils.toString(entity, StandardCharsets.UTF_8);

        if (statusCode == 200) {
            return JSON.parseObject(responseBody, YxhtSmsResponseDto.class);
        } else {
            log.error("易信华泰短信平台调用失败，状态码：{}，响应：{}", statusCode, responseBody);
            throw new RuntimeException("短信平台调用失败，状态码：" + statusCode);
        }
    }

    /**
     * 保存API调用日志
     */
    private void saveApiLog(String mobile, String message, String apiParams, String apiCallback) {
        try {
            YxhtApiLog log = new YxhtApiLog();
            log.setMobile(mobile);
            log.setMessage(message);
            log.setApiParams(apiParams);
            log.setApiCallback(apiCallback);
            log.setCreateTime(LocalDateTime.now());
            yxhtApiLogMapper.insert(log);
        } catch (Exception e) {
            log.error("保存API调用日志失败", e);
        }
    }
} 